
#ifndef __APR_READ_WRITE_MUTEX_H
#define __APR_READ_WRITE_MUTEX_H

#include "../iface/APRInterface.h"
#include <apr_thread_rwlock.h>

/** A wrapper around the APR read/write mutex. */
class APRRWMutex
{
   private:
      /** Initialise the APR read/write mutex object.
       * 
       * @param mp The memory pool to use to allocate space for this
       * mutex. */
      bool init(apr_pool_t *mp)
      {
         apr_status_t status;
         status = apr_thread_rwlock_create(&aprt_rwmutex, mp);
         CheckAPRError(status);
         return true;
      }
      /** Destroy the APR read/write mutex object. */
      bool destroy()
      {
         apr_status_t status;
         status = apr_thread_rwlock_destroy(aprt_rwmutex);
         CheckAPRError(status);
         return true;
      }
   protected:
      /** The read/write mutex being wrapped. */
      apr_thread_rwlock_t *aprt_rwmutex;
   public:
      /** Initialise the wrapper and the wrapped read/write mutex
       * using the given memory pool. */
      APRRWMutex(apr_pool_t *mp) { init(mp); }
      /** Destructor for the wrapper and the wrapped read/write
       * mutex. */
      virtual ~APRRWMutex() { destroy(); }
      /** Lock the resource (the current thread is reading from
       * it). */
      bool lockRead()
      {
         apr_status_t status;
         status = apr_thread_rwlock_rdlock(aprt_rwmutex);
         //CheckAPRError(status);
         return true;
      }
      /** Unlock the resource (the current thread is no longer reading
       * from it). */
      bool unlockRead() { unlock(); return true; }
      /** Lock the resource (the current thread is writing to it). */
      bool lockWrite()
      {
         apr_status_t status;
         status = apr_thread_rwlock_wrlock(aprt_rwmutex);
         CheckAPRError(status);
         return true;
      }
      /** Unlock the resource (the current thread is no longer writing
       * to it). */
      bool unlockWrite() { unlock(); return true; }
      /** Unlock whichever of read or write has been previously
       * locked. */
      bool unlock()
      {
         apr_status_t status;
         status = apr_thread_rwlock_unlock(aprt_rwmutex);
         //CheckAPRError(status);
         return true;
      }
};

#endif
